package org.springside.examples.showcase.wb.web;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springside.examples.showcase.utilities.wb.SinaMid2Url;
import org.springside.examples.showcase.utilities.wb.SinaWbParse;
import org.springside.examples.showcase.wb.entity.TreeEdge;
import org.springside.examples.showcase.wb.entity.TreeNode;
import org.springside.examples.showcase.wb.entity.WbContent;
import org.springside.examples.showcase.wb.entity.WbContentRet;
import org.springside.examples.showcase.wb.service.WbContentManager;
import org.springside.modules.mapper.JsonMapper;
import org.springside.modules.utils.RegexUtil;

@Controller
public class WbSpreadController {
	/**
	 * 列表框架页面，仅仅为了展示（Framset），具体逻辑交由具体的其他ajax
	 */
	@RequestMapping(value = "/wb/spread")
	public String list() {
		return "wb/spread";
	}

	/**
	 * 展示某地址的微博内容
	 * 
	 * @param nedAnalyzedUrl 微博url
	 * @return json格式的微博内容
	 */
	@RequestMapping(value = "/json/content")
	@ResponseBody
	public String detail(@RequestParam String nedAnalyzedUrl) {
		String uid = RegexUtil.getMatchGroup(nedAnalyzedUrl, "(http://weibo.com/(.*)/(.*))", 2);
		String _mid = RegexUtil.getMatchGroup(nedAnalyzedUrl, "(http://weibo.com/(.*)/(.*))", 3);
		Long mid = Long.valueOf(SinaMid2Url.url2mid(_mid));
		// 获取主帖
		WbContent wbContent = wbContentManager.get(mid, uid);
		String json = mapper.toJson(wbContent);
		System.out.println(json);
		return json;
	}

	/**
	 * 微博传播路径
	 * 
	 * @param nedAnalyzedUrl
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/json/spreadRoad.json")
	@ResponseBody
	public String spread(@RequestParam String nedAnalyzedUrl) throws Exception {
		if (StringUtils.isEmpty(nedAnalyzedUrl)) {
			throw new Exception();
		}
		String uid = RegexUtil.getMatchGroup(nedAnalyzedUrl, "(http://weibo.com/(.*)/(.*))", 2);
		String _mid = RegexUtil.getMatchGroup(nedAnalyzedUrl, "(http://weibo.com/(.*)/(.*))", 3);
		Long mid = Long.valueOf(SinaMid2Url.url2mid(_mid));

		// 获取主帖
		WbContent wbContent = wbContentManager.get(mid, uid);
		// 获取跟帖
		List<WbContentRet> commentFeeds = wbContentManager.getComments("" + mid, uid, 500);

		// 用户名到节点id的映射
		Map<String, Integer> screenname2nodeid = new HashMap<String, Integer>();
		// 节点id到节点
		Map<Integer, TreeNode> treeNodes = new HashMap<Integer, TreeNode>();
		// 节点id到子节点集合
		Map<Integer, List<TreeEdge>> treeEdges = new HashMap<Integer, List<TreeEdge>>();
		// 有向线段（x,y）到线段对象
		Map<String, TreeEdge> xyNodeEdges = new HashMap<String, TreeEdge>();

		TreeNode treeNode = disposeUserRelation(wbContent, commentFeeds, screenname2nodeid, treeNodes, treeEdges, xyNodeEdges);

		List<TreeNode> treeNodesList = new ArrayList<TreeNode>();
		treeNodesList.addAll(treeNodes.values());

		// 处理第一层的角度，360/总结点数
		int i = 0;
		List<TreeEdge> edges = treeEdges.get(treeNode.getId());
		for (TreeEdge treeEdge : edges) {
			TreeNode node = treeNodes.get(treeEdge.getToId());
			node.setDegree(Math.PI * 2 * i++ / edges.size());
			double x = Math.cos(node.getDegree()) * 200;
			double y = Math.sin(node.getDegree()) * 200;
			node.setX(x);
			node.setY(y);
			List<TreeEdge> list = treeEdges.get(node.getId());
			// System.out.println("^" + node.getId() + "\t" + node.getKey() + "\t" + node.getX() + "\t" + node.getY());
			disposeSons(node, treeEdges, treeNodes, xyNodeEdges);
		}

		// 节点的边
		List<TreeEdge> treeEdgesList = new ArrayList<TreeEdge>();
		Collection<List<TreeEdge>> values = treeEdges.values();
		for (List<TreeEdge> treeEdgeList : values) {
			treeEdgesList.addAll(treeEdgeList);
		}

		Map treeResultMap = new HashMap();
		treeResultMap.put("nodes", treeNodesList);
		treeResultMap.put("edges", treeEdgesList);

		// for (TreeNode node : treeNodesList) {
		// System.out.println(node.getId() + "\t" + node.getKey() + "\t" + node.getX() + "\t" + node.getY());
		// }
		// for (TreeEdge edge : treeEdgesList) {
		// System.out.println(edge.getId() + "\t" + edge.getFromId() + "\t" + edge.getToId());
		// }

		String json = mapper.toJson(treeResultMap);
		return json;
	}

	private TreeNode disposeUserRelation(WbContent wbContent, List<WbContentRet> commentFeeds, Map<String, Integer> screenname2nodeid, Map<Integer, TreeNode> treeNodes, Map<Integer, List<TreeEdge>> treeEdges, Map<String, TreeEdge> xyNodeEdges) {
		int countNode = 0;
		int countEdge = 0;
		int level = 0;
		TreeNode treeNode = new TreeNode();
		treeNode.setId(countNode++);
		treeNode.setKey(wbContent.getIr_screen_name().trim());
		treeNode.setLevel(level);
		treeNode.setValue(treeNode.getValue() + 1);
		treeNodes.put(treeNode.getId(), treeNode);
		screenname2nodeid.put(wbContent.getIr_screen_name(), treeNode.getId());
		treeEdges.put(treeNode.getId(), new ArrayList<TreeEdge>());

		// 打印可视化结果
		for (WbContentRet wb : commentFeeds) {
			String[] su = SinaWbParse.getSpreadRoad(wb);
			TreeNode fromNode = treeNode;
			level = 1;
			for (String screenname : su) {
				List<String> matchGroupList2 = null;
				TreeNode treeNode1 = null;
				if (screenname.contains("@")) {
					matchGroupList2 = RegexUtil.getMatchGroupList(screenname, "(@([^@,]*),)", 2);
					screenname = screenname.replaceAll("(\\(.*\\))", "");
				}
				screenname = screenname.trim();
				Integer nodeIndex = screenname2nodeid.get(screenname);
				if (nodeIndex != null) {
					treeNode1 = treeNodes.get(nodeIndex);
					treeNode1.setValue(treeNode1.getValue() + 1);
					TreeEdge treeEdge = xyNodeEdges.get(fromNode.getId() + "-" + treeNode1.getId());
					if (treeEdge == null) {
						treeEdge = new TreeEdge();
						treeEdge.setId(countEdge++);
						treeEdge.setFromId(fromNode.getId());
						treeEdge.setToId(treeNode1.getId());
						// 添加新生成的边（两个节点已经存在，但是没有连线的情况）
						xyNodeEdges.put(fromNode.getId() + "-" + treeNode1.getId(), treeEdge);

						List<TreeEdge> edgesInNodeId = treeEdges.get(fromNode.getId());
						if (edgesInNodeId == null) {
							edgesInNodeId = new ArrayList<TreeEdge>();
							treeEdges.put(fromNode.getId(), edgesInNodeId);
						}
						edgesInNodeId.add(treeEdge);
					}
				} else {
					treeNode1 = new TreeNode();
					treeNode1.setKey(screenname);
					treeNode1.setId(countNode++);
					treeNode1.setLevel(level++);
					treeNode1.setValue(treeNode.getValue() + 1);
					treeNodes.put(treeNode1.getId(), treeNode1);
					screenname2nodeid.put(screenname, treeNode1.getId());

					TreeEdge treeEdge = new TreeEdge();
					treeEdge.setId(countEdge++);
					treeEdge.setFromId(fromNode.getId());
					treeEdge.setToId(treeNode1.getId());
					List<TreeEdge> edgesInNode = treeEdges.get(fromNode.getId());
					if (edgesInNode == null) {
						edgesInNode = new ArrayList<TreeEdge>();
						treeEdges.put(fromNode.getId(), edgesInNode);
					}
					edgesInNode.add(treeEdge);
					xyNodeEdges.put(fromNode.getId() + "-" + treeNode1.getId(), treeEdge);

					fromNode = treeNode1;
				}

				if (matchGroupList2 != null) {
					// 西伯利亚大尾巴狼-->张栋_机器学习(@王江民,)-->ii32
					// 处理“王江民”的情况
					for (String tosb : matchGroupList2) {
						tosb = tosb.trim();
						Integer nodeIndex2 = screenname2nodeid.get(tosb);
						TreeNode treeNode2 = null;
						if (nodeIndex2 != null) {// 该用户名的节点已经存在了
							treeNode2 = treeNodes.get(nodeIndex2);
							treeNode2.setValue(treeNode2.getValue() + 1);
							TreeEdge treeEdge = xyNodeEdges.get(treeNode1.getId() + "-" + treeNode2.getId());
							if (treeEdge == null) {
								treeEdge = new TreeEdge();
								treeEdge.setId(countEdge++);
								treeEdge.setFromId(treeNode1.getId());
								treeEdge.setToId(treeNode2.getId());
								// 添加新生成的边（两个节点已经存在，但是没有连线的情况）
								xyNodeEdges.put(treeNode1.getId() + "-" + treeNode2.getId(), treeEdge);

								List<TreeEdge> edgesInNodeId = treeEdges.get(treeNode1.getId());
								if (edgesInNodeId == null) {
									edgesInNodeId = new ArrayList<TreeEdge>();
									treeEdges.put(treeNode1.getId(), edgesInNodeId);
								}
								edgesInNodeId.add(treeEdge);
							}
						} else {// 不存在，就创建一个
							treeNode2 = new TreeNode();
							treeNode2.setId(countNode++);
							treeNode2.setKey(tosb);
							treeNode2.setLevel(level);
							treeNode2.setValue(treeNode2.getValue() + 1);
							screenname2nodeid.put(tosb, treeNode2.getId());
							treeNodes.put(treeNode2.getId(), treeNode2);

							TreeEdge treeEdge = new TreeEdge();
							treeEdge.setId(countEdge++);
							treeEdge.setFromId(treeNode1.getId());
							treeEdge.setToId(treeNode2.getId());
							// 张栋_机器学习(@王江民,) ，我们应该针对的是“张栋_机器学习”的边
							List<TreeEdge> edgesInNodeId = treeEdges.get(treeNode1.getId());
							if (edgesInNodeId == null) {
								edgesInNodeId = new ArrayList<TreeEdge>();
								treeEdges.put(treeNode1.getId(), edgesInNodeId);
							}
							edgesInNodeId.add(treeEdge);
							xyNodeEdges.put(treeNode1.getId() + "-" + treeNode2.getId(), treeEdge);
						}
					}
				}
			}
		}
		return treeNode;
	}

	/**
	 * 处理2级以上节点的位置
	 * 
	 * @param node 相当于父节点，根据父节点，定位子节点的位置坐标
	 * @param treeEdges 父节点对应子节点的映射
	 * @param treeNodes 树节点Id对应的节点对象
	 */
	private void disposeSons(TreeNode node, Map<Integer, List<TreeEdge>> treeEdges, Map<Integer, TreeNode> treeNodes, Map<String, TreeEdge> xyNodeEdges) {
		List<TreeEdge> list = treeEdges.get(node.getId());
		if (list == null || list.size() < 1) {
			return;
		}
		int i = 0;
		for (TreeEdge treeEdge : list) {
			TreeNode treeNode = treeNodes.get(treeEdge.getToId());
			treeNode.setDegree(node.getDegree() + (Math.PI * 2 * i++ / (list.size() * 3)));
			double x = Math.cos(treeNode.getDegree()) * 90;
			double y = Math.sin(treeNode.getDegree()) * 90;
			treeNode.setX(node.getX() + x);
			treeNode.setY(node.getY() + y);
			// System.out.println("*" + treeNode.getId() + "\t" + treeNode.getKey() + "\t" + treeNode.getX() + "\t" + treeNode.getY());
			if (xyNodeEdges.get(treeNode.getId() + "-" + node.getId()) == null) {
				disposeSons(treeNode, treeEdges, treeNodes, xyNodeEdges);
			}
		}
	}

	@Autowired
	private WbContentManager wbContentManager;

	private JsonMapper mapper = JsonMapper.buildNonEmptyMapper();
}
